package com.atguigu.stack;

/**
 * @author 龍
 * 栈实现综合计算器（中缀表达式）
 * 1 显示一位数的运算
 * 2 实现多位数的运算
 * 3 课后练习--给表达式加入小括号
 */
public class Calculator {
    public static void main(String[] args) {
        //设置一个表达式
        String expression = "20*6+3-15";
        //创建两个栈
        ArrayStack2 numStack = new ArrayStack2(10);
        ArrayStack2 opeStack = new ArrayStack2(10);
        //定义扫描的索引
        int index=0;
        int num1=0;
        int num2=0;
        int ope=0;
        int result=0;
        //将每次扫描的char保存到ch
        char ch=' ';
        //用于拼接多位数
        String keepNum="";
        while (true){
            //一次得到expression的每一个字符
            ch=expression.substring(index,index+1).charAt(0);
            //判断是数字还是符号
            if (opeStack.isOpe(ch)){
                //判断是否为空
                if (!opeStack.isEmpty()){
                    //不为空，进行和符号栈顶的操作符进行优先级比较
                    if (opeStack.priority(ch)<=opeStack.priority(opeStack.peek())){
                        //数栈抛出两个数进行运算
                        num1=numStack.pop();
                        num2=numStack.pop();
                        ope=opeStack.pop();
                        result=numStack.cal(num1,num2,ope);
                        //将当前运算结果存放到数栈
                        numStack.push(result);
                        //将当前的操作符入操作符栈
                        opeStack.push(ch);
                    }else {
                        //操作符的优先级大于栈顶的优先级
                        opeStack.push(ch);
                    }
                }else{
                    //符号栈为空,符号直接入栈
                    opeStack.push(ch);
                }
            }else {
                //ch是字符类型，需要转换为int类型的数字(当发现是一个数字的时候不能直接入栈，可能是多位数)
                //numStack.push(ch-48);
                //if(expression.sub)
                  keepNum+=ch;
                  //
                if (index==expression.length()-1){
                    numStack.push(Integer.parseInt(keepNum));
                    break;
                }else{
                    //判断下一个字符是不是数组，如果是数字，如果是就继续运算
                    if (opeStack.isOpe(expression.substring(index+1,index+2).charAt(0))){
                        //如果是运算符，则入栈
                        numStack.push(Integer.parseInt(keepNum));
                        //keepNum要清空(重点)
                        keepNum="";
                    }
                }


            }
            index++;
            if (index >=expression.length()) {
                break;
            }
        }
        //表达式稻苗完毕，就从数栈，符号栈中pop出响应的数和符号进行计算，并运行
        while(true){
            if (opeStack.isEmpty()){
                break;
            }
            num1=numStack.pop();
            num2=numStack.pop();
            ope=opeStack.pop();
            result=numStack.cal(num1,num2,ope);
            numStack.push(result);
        }
        //将数栈的最后的一个数字抛出
        System.out.println("表达式"+expression+"="+numStack.pop());

    }

}

class ArrayStack2 {
    private int maxSize;
    private int[] stack;
    private int top = -1;

    /**
     * 构造器
     */
    public ArrayStack2(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[this.maxSize];
    }

    /**
     * 栈满
     */
    public boolean isFull() {
        return top == maxSize - 1;
    }

    /**
     * 栈空
     */
    public boolean isEmpty() {
        return top == -1;
    }

    /**
     * 入栈
     */
    public void push(int value) {
        if (isFull()) {
            System.out.println("栈已经满了！！！");
            return;
        }
        top++;
        stack[top] = value;
    }

    /**
     * 出栈
     */
    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈已经空了！！！");
        }
        int value = stack[top];
        top--;
        return value;
    }
    /**
     * 可以查看栈顶的值，不是pop
     */
    public int peek(){
        return stack[top];
    }

    /**
     * 遍历栈，遍历的时候从栈顶开始显示数据
     */
    public void list() {
        if (isEmpty()) {
            System.out.println("栈是空的！！！");
        }
        for (int i = top; i >= 0; i--) {
            System.out.println("stack[" + i + "]" + stack[i]);
        }
    }
    /**
     * 返回运算符的优先级，优先级由程序员来确定，优先级使用数字来进行表示
     */
    public int priority(int ope){
        if (ope=='*'||ope=='/'){
            return 1;
        }else if (ope=='+'||ope=='-'){
            return 0;
        }else {
            //表达式存在问题
            return -1;
        }
    }
    /**
     * 判断是不是一个运算符
     */
    public boolean isOpe(char val){
        return val=='+'||val=='-'||val=='*'||val=='/';
    }
    /**
     * 计算方法
     */
    public int cal(int num1,int num2,int ope){
        int result=0;
        switch (ope){
            case '+':
                result=num1+num2;
                break;
            case '-':
                result=num2-num1;
                break;
            case '*':
                result=num1*num2;
                break;
            case '/':
                result=num2/num1;
                break;
            default:break;
        }
        return result;
    }

}
